#include "StdAfx.h"
#include "Vector4.h"


CVector4::CVector4(void)
: x(0.f)
, y(0.f)
, z(0.f)
, w(0.f)
{
}

CVector4::CVector4(DATA_TYPE x_, DATA_TYPE y_, DATA_TYPE z_, DATA_TYPE w_)
: x(x_)
, y(y_)
, z(z_)
, w(w_)
{

}

CVector4::~CVector4(void)
{
}

DATA_TYPE& CVector4::operator[](unsigned int idx)
{
	switch (idx)
	{
	case 0:
		return x;
	case 1:
		return y;
	case 2:
		return z;
	case 3:
		return w;
	default:
		cout << "out of bound\n";
		break;
	}

	return x;
}

DATA_TYPE CVector4::operator[] (unsigned int idx) const
{
	switch (idx)
	{
	case 0:
		return x;
	case 1:
		return y;
	case 2:
		return z;
	case 3:
		return w;
	default:
		cout << "out of bound\n";
		break;
	}

	return x;
}

CVector4 CVector4::Interpolate(DATA_TYPE a, DATA_TYPE b, DATA_TYPE c, const CVector4& vec0, const CVector4& vec1, const CVector4& vec2)
{
	CVector4 ret;
	ret = vec0 * a + vec1 * b + vec2 * c;

	return ret;
}

CVector4 CVector4::Interpolate(DATA_TYPE a, const CVector4& vec0, const CVector4& vec1)
{
	CVector4 ret;
	ret = vec0 * (1.f - a) + vec1 * a;

	return ret;
}

CVector4 CVector4::operator-() const
{
	CVector4 ret;
	ret.x = -this->x;
	ret.y = -this->y;
	ret.z = -this->z;
	ret.w = -this->w;

	return ret;
}

CVector4 CVector4::operator+(const CVector4& rhs) const
{
	CVector4 ret;
	ret.x = this->x + rhs.x;
	ret.y = this->y + rhs.y;
	ret.z = this->z + rhs.z;
	ret.w = this->w + rhs.w;

	return ret;
}

CVector4 CVector4::operator-(const CVector4& rhs) const
{
	CVector4 ret;
	ret.x = this->x - rhs.x;
	ret.y = this->y - rhs.y;
	ret.z = this->z - rhs.z;
	ret.w = this->w - rhs.w;

	return ret;
}

CVector4 CVector4::operator*(const CVector4& rhs) const
{
	CVector4 ret;
	ret.x = this->x * rhs.x;
	ret.y = this->y * rhs.y;
	ret.z = this->z * rhs.z;
	ret.w = this->w * rhs.w;

	return ret;
}

CVector4 CVector4::operator*(DATA_TYPE fScalar) const
{
	CVector4 ret;
	ret.x = this->x * fScalar;
	ret.y = this->y * fScalar;
	ret.z = this->z * fScalar;
	ret.w = this->w * fScalar;

	return ret;
}

CVector4 CVector4::operator/(DATA_TYPE fScalar) const
{
	CVector4 ret;
	ret.x = this->x / fScalar;
	ret.y = this->y / fScalar;
	ret.z = this->z / fScalar;
	ret.w = this->w / fScalar;

	return ret;
}

DATA_TYPE CVector4::GetDistance(const CVector4& vec0, const CVector4& vec1)
{
	DATA_TYPE fSqDist = ((vec0.x - vec1.x) * (vec0.x - vec1.x)) +
						((vec0.y - vec1.y) * (vec0.y - vec1.y)) +
						((vec0.z - vec1.z) * (vec0.z - vec1.z));
	return sqrtf(fSqDist);
}

DATA_TYPE CVector4::Dot(const CVector4& rhs) const
{
	DATA_TYPE ret = 0.f;
	ret += this->x * rhs.x;
	ret += this->y * rhs.y;
	ret += this->z * rhs.z;
	ret += this->w * rhs.w;
	return ret;
}

CVector4 CVector4::Cross3(const CVector4& rhs) const
{
	CVector4 ret;
	ret.x = this->y * rhs.z - this->z * rhs.y;
	ret.y = this->z * rhs.x - this->x * rhs.z;
	ret.z = this->x * rhs.y - this->y * rhs.x;
	return ret;
}

CVector4 CVector4::Normalize() const
{
	DATA_TYPE length = GetLength();
	CVector4 ret = (*this) / length;
	return ret;
}

DATA_TYPE CVector4::GetLength() const
{
	return sqrtf(x*x + y*y + z*z + w*w);
}